package com.sj.utils;

import com.sj.pojo.FirstProtocol;
import com.sj.pojo.MsgTypeEnum;
import com.sj.pojo.Protocol;

import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * User: xiaoqi
 * Date: 2022-07-07
 * Time: 上午 11:16
 * Description: 传输工具类
 *
 * @author xiaoqi
 * @since 2022-07-07
 */
public class TransferUtils {

    private static Protocol protocol;

    static {
        protocol = new FirstProtocol();
    }

    public static void send(Protocol protocol, SocketChannel socketChannel) {
        try {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            // 返回类型
            buffer.put(protocol.getHeader().getMsgType());
            // 返回消息体长度
            buffer.putInt(protocol.getHeader().getMsgLen());
            // 返回消息体内容
            buffer.put(protocol.getContent().getBytes());
            buffer.flip();
            socketChannel.write(buffer);
        } catch (IOException e) {
            System.out.println("断开了一个连接");
        }
    }


    public static Protocol receive(SocketChannel socketChannel) {
        try {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int read = socketChannel.read(buffer);
            if (read > 5) {
                buffer.flip();
                byte msgType = buffer.get();
                int msgLen = buffer.getInt();
                byte[] bytes = new byte[msgLen];
                System.out.println("buffer.limit() = " + buffer.limit());
                System.out.println("buffer.position() = " + buffer.position());
                while (buffer.position() <= msgLen) {
                    buffer.get(bytes, 0, buffer.limit() - buffer.position());
                }
                return protocol.getProtocol(msgType, new String(bytes, 0, bytes.length));
            }
        } catch (IOException e) {
            System.out.println("断开了一个连接");
        }
        return null;
    }

    public static Protocol check(String[] instruct, Integer len) {
        return check(instruct, len, false, null);
    }


    public static Protocol check(String[] instruct, Integer len, boolean isExist, Map data) {
        if (instruct.length != len) {
            return protocol.getProtocol(MsgTypeEnum.RESPONSE, "错误的命令");
        }
        if (isExist) {
            Object o = data.get(instruct[1]);
            if (o == null) {
                return protocol.getProtocol(MsgTypeEnum.RESPONSE, instruct[1] + " is undefine!");
            }
            if (o instanceof Map) {
                Map<String, String> map = (Map<String, String>) o;
                if (map.get(instruct[2]) == null) {
                    return protocol.getProtocol(MsgTypeEnum.RESPONSE, instruct[2] + " is undefine!");
                }
            }
        }
        return null;
    }

    public static String joint(String[] instruct, int index) {
        StringBuilder res = new StringBuilder();
        for (int i = index; i < instruct.length; i++) {
            res.append(instruct[i]);
            res.append(" ");
        }
        return res.substring(0, res.length() - 1);
    }

    public static String inOrDecrBy(String str, Integer step) {
        BigInteger bigInteger = null;
        try {
            bigInteger = new BigInteger(str);
        } catch (Exception e) {
            return str + " is not a number!";
        }
        return bigInteger.add(BigInteger.valueOf(step)).toString();
    }


    public static Protocol cyBy(String[] instruct, Integer len, boolean isExists, Map data, Integer step) {
        Protocol check = TransferUtils.check(instruct, len, isExists, data);
        if (check != null) {
            return check;
        }
        String str = (String) data.get(instruct[1]);
        String res = TransferUtils.inOrDecrBy(str, step);
        if (res.endsWith("is not a number!")) {
            return protocol.getProtocol(MsgTypeEnum.RESPONSE, res);
        }
        data.put(instruct[1], res);
        return protocol.getProtocol(MsgTypeEnum.RESPONSE, res);
    }
}